
package org.sidora.core;


import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

//import matrix.Diagrama;
//import matrix.PersistedData;

import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Predicate;
import org.sidora.core.context.Context;
import org.sidora.core.util.AbstractFactory;
import org.sidora.core.util.AbstractInventory;
import org.sidora.core.util.OCProvider;
import org.sidora.core.util.ParameterCollector;

/**
 * Sector
 * @author Enric Tartera,Juan Manuel Gimeno, Roger Masgoret
 * @version 1.0
 */
public class Sector implements Comparable{
    
    
    private KeyObject idSector;
    
    private String commentary;
    
    //private Zone zone;
    //private Map <Sector> synchronics= new HashMap();
    //private Map <Sector> diachronics= new HashMap();
    
    //private Set <Context> contexts = new HashSet();
    //private Set <Feature>features= new HashSet();
    private boolean closed = false;
    
//    private PersistedData diagrama;
    
    private Sector(){}
    
    public boolean isClosed() {
        return closed;
    }
    public void setClosed(boolean closed) {
        this.closed = closed;
    }
    public List<Context> getDBContexts() {
        Sector sector = this;
        return Context.Inventory.getList(sector);
    }

    public Set<Context> getContexts() {
        return new TreeSet<Context>(Context.Inventory.getList(this));
    }
    
    public Set<Feature> getFeatures() {
        return new TreeSet<Feature>(Feature.Inventory.getList(this));
    }

    public KeyObject getIdSector() {
        return idSector;
    }
    public void setIdSector(KeyObject idSector) {
        this.idSector = idSector;
    }
    
//    public PersistedData getDiagrama() {
//        return diagrama;
//    }
//    
//    public void setDiagrama(PersistedData diagrama) {
//        this.diagrama = diagrama;
//    }
    
    @Override
    public boolean equals(Object obj) {
        if (obj == this)	return true;
        if (!(obj instanceof Sector)) return false;
        Sector sector = null;
        try {
            sector = (Sector) obj;
        } catch (Exception e) {
            return false;
        }
        if (this.getIdSector() != sector.getIdSector()) return false;
        return true;
    }
    
    @Override
    public String toString() {
        String text= "Sector: "+getIdSector().getZone().getIdZone()+"."+getIdSector().getNumber();//
        return text;
    }
    
    
//    private static class Factory extends AbstractFactory{
//        
//        protected Object create(ParameterCollector param) {
//            // La pol�tica de creaci� de sectors determina que un usuari
//            // amb rol "admin" o "user" pot crear noves inst�ncies.
//            // Per defecte es permet tamb? el password de root declarat com a variable est�tica de User
//            
//
//                    return new Sector();
//
//            
//        }
//    }
    public static class Inventory extends AbstractInventory{
        
        public boolean exist(final KeyObject id) throws Exception{
            
            ObjectContainer db = OCProvider.getInstance();
            ObjectSet<Sector> sectors = db.query(new Predicate<Sector>() {
                public boolean match(Sector candidate) {
                    return candidate.getIdSector().equals(id);
                }
            });
            
            if (sectors.hasNext()){
                return true;
            } else {
                return false;
            }
        }
        
        public Sector getNewObject(ParameterCollector param) throws Exception{
            // Delega en la factoria corresponent la creaci� d'un nou sector en
            // el cas que aquesta no existeixi
            

            
            //Verifica si existeix en la base d'objectes
            
            KeyObject newId= getNewKey(param);
            
            
            //Delega en la factoria la creaci�
            //	param.put("siteid", getNewKey());
            Sector sector = new Sector(); //(Sector) Sector.Factory.createObject(param);
            
            sector.setIdSector(newId);
            Zone zone = (Zone) param.get("zone");
            zone.getSectors().add(sector);
            return sector;
            
        }
        
        public KeyObject getNewKey(ParameterCollector param) {
            //Cal passar una inst�ncia de KeyObject amb la zona corresponent
            final Zone zone = (Zone) param.get("zone");
            //se li dona el valor inicial per defecte
            KeyObject key = new KeyObject();
            key.setNumber(1);
            key.setZone(zone);
            key.setSite(zone.getSite());
            //es busca a la base d'objectes totes les inst�ncies de Sectors de la Zona indicada
            ObjectContainer db = OCProvider.getInstance();
            List <Sector>sectors = db.query(new Predicate <Sector> (){
                @Override
                public boolean match(Sector candidate) {
                    return candidate.getIdSector().getZone().equals(zone);
                }
            });
            //En cas que hi hagi d'altres sectors a la zona busca el m�s alt i en suma un
            if (sectors.size()!= 0){
                
                TreeSet <Sector> tree = new TreeSet<Sector>(sectors);
                Sector sector = tree.last();
                Integer integer = sector.getIdSector().getNumber()+1;
                key.setNumber(integer);
                return key;
            }
            //En cas contrari pasa el valor per defecte
            else return key;
            
        }
        
        
        public Object getObject(ParameterCollector param) {
            //Carrega el Site amb el corresponent siteid
            final KeyObject key = (KeyObject) param.get("id");
            ObjectContainer db = OCProvider.getInstance();
            
            ObjectSet <Sector> sectors = db.query(new Predicate <Sector>() {
                public boolean match(Sector asector) {
                    return (asector.getIdSector().equals(key));
                }
            });
            
            if (sectors.hasNext()){
                return sectors.next();
            } else throw new RuntimeException("Sector inexistent");
        }
        
        public static List getList() {
            
            ObjectContainer db = OCProvider.getInstance();
            List<Sector> list = db.query(Sector.class);
            
            return list;
            
        }
        
        
        public static List<Sector> getList(final Site site) {
            ObjectContainer db = OCProvider.getInstance();
            List<Sector> list = db.query(new Predicate <Sector> (){
                
                @Override
                public boolean match(Sector sector) {
                    
                    return sector.getIdSector().getSite() == site;
                }});
                
                return list;
        }
        
        public static List<Sector> getList(final Zone zone) {
            ObjectContainer db = OCProvider.getInstance();
            List<Sector> list = db.query(new Predicate <Sector> (){
                
                @Override
                public boolean match(Sector sector) {
                    
                    return sector.getIdSector().getZone()==zone;
                }});
                
                return list;
        }
    }
    public int compareTo(Object obj) {
        Sector asector = (Sector) obj;
        return this.getIdSector().compareTo(asector.getIdSector());
    }

    public String getCommentary() {
        return commentary;
    }

    public void setCommentary(String commentary) {
        this.commentary = commentary;
    }
    
    
} // end Sector



